﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Myotragus.Data.Containers
{
	public class TypeFinder : ITypeFinder
	{
		private static readonly Regex PlainTypeName = new Regex(@"\w+(\.\w+)*");

		protected IEntitiesContainer Entities { get; private set; }

		public TypeFinder(IEntitiesContainer entities)
		{
			Entities = entities;
		}

		public Type FindType(string name, params string[] genericArguments)
		{
			return FindType(name, (IEnumerable<string>)genericArguments);
		}

		public Type FindType(string name, IEnumerable<string> genericArguments)
		{
			return FindType(Entities, name, genericArguments);
		}

		private static Type FindType(IEntitiesContainer entities, string name,
			IEnumerable<string> genericArgs)
		{
			return entities.Interfaces.FirstOrDefault(e => NameMatches(e, name) &&
				GenericArgumentMatch(e.GetGenericArguments(), genericArgs.ToArray()));
		}

		private static bool GenericArgumentMatch(IEnumerable<Type> genericArguments,
			IList<string> genericArgumentNames)
		{
			return !genericArguments.Where((t, i) => !NameMatches(t, genericArgumentNames[i])).Any();
		}

		private static bool NameMatches(Type type, string name)
		{
			return GetPlainTypeName(type.Name) == name ||
				GetPlainTypeName(type.FullName) == name;
		}

		private static string GetPlainTypeName(string fullName)
		{
			var match = PlainTypeName.Match(fullName);
			return match.Value;
		}
	}
}